package com.netpace.iem.umair.model;

import java.util.Calendar;
import java.util.List;
import org.apache.log4j.Logger;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.netpace.iem.umair.dal.*;
import com.netpace.iem.umair.helper.Console;

public class Main {
	
	IIncomeDao incomeMemory;
	IExpenseDao expenseMemory;
	IItemDao itemMemory;
	ICategoryDao categoryMemory;
	IUnitDao unitMemory;
	ILabelDao labelMemory;
	
	static Logger log = 
		   Logger.getLogger(Main.class.getName());

	private Main(IIncomeDao incomeMemory, IExpenseDao expenseMemory,
				IItemDao itemMemory, ICategoryDao categoryMemory,
				IUnitDao unitMemory, ILabelDao labelMemory) {
		this.incomeMemory = incomeMemory;
		this.expenseMemory = expenseMemory;
		this.itemMemory = itemMemory;
		this.categoryMemory = categoryMemory;
		this.unitMemory = unitMemory;
		this.labelMemory = labelMemory;
		
	}
	
	@SuppressWarnings("resource")
	public static void main(String[] args) {
		
		System.out.println("Welcome to PEMS");
		ApplicationContext context = new ClassPathXmlApplicationContext("ApplicationContext.xml");
		Main m = (Main) context.getBean("main");
		
		while(true) {
			m.mainMenu();
		}

	}
	
	private void mainMenu() {
        System.out.println("Choose from Main Menu");
        System.out.println("1- New Transaction");
        System.out.println("2- Update Transaction");
        System.out.println("3- Delete Transaction");
        System.out.println("4- Display Reports");
        System.out.println("5- Exit");

        String choice = Console.readLine();

        switch (choice) {
            case "1":  newTransaction();
            			break;

            case "2":   updateTransaction();
                        break;
                        
            case "3":   deleteTransaction();
            			break;         

            case "4":   displayReport();
                        break;

            case "5":   System.out.println("Exiting...");
                        System.exit(0);

            default:    System.out.println("Invalid Choice exiting...");
                        System.exit(0);
        }

        return;

	}
	
	private void updateTransaction() {
		System.out.println("1- Income Update");
		System.out.println("2- Expense Update");
		
        String choice = Console.readLine();

        switch (choice) {
        case "1":  incomeUpdate();
        			break;
        			
        case "2":   expenseUpdate();
                    break;

        default:    System.out.println("Invalid Choice exiting...");
                    System.exit(0);
        }

        return;
	}

	private void expenseUpdate() {
		System.out.println("Enter Expense Id to Update: ");
		int id = Console.readInt();
		
		System.out.println("To Enter Updated Category: ");
		int catId = newCategory();
		
		System.out.println("Enter Updated Date: ");
		Calendar date = Console.readDate();
		
		System.out.println("Enter Updated Item; ");
		List<Item> items = newItems();
		
		System.out.println("To Enter Updated Label; ");
		List<Label> lables = newLabels();
		
		Expense updatedExpense = new Expense(id, items, lables, categoryMemory.findById(catId), date);
		expenseMemory.update(updatedExpense, id);
	}

	private void incomeUpdate() {
		System.out.println("Enter Income Id to Update: ");
		int id = Console.readInt();
		
		System.out.println("To Enter Updated Category: ");
		int catId = newCategory();
		
		System.out.println("Enter Updated Date: ");
		Calendar date = Console.readDate();
		
		System.out.println("Enter Updated Amount; ");
		int amount = Console.readInt();
		
		Income updatedIncome = new Income(id, categoryMemory.findById(catId), amount, date);
		incomeMemory.update(updatedIncome, id);
	}

	private void deleteTransaction() {
		System.out.println("1- Income Delete");
		System.out.println("2- Expense Delete");
		
        String choice = Console.readLine();

        switch (choice) {
        case "1":  	incomeDelete();
        			break;
        			
        case "2":   expenseDelete();
                    break;

        default:    System.out.println("Invalid Choice exiting...");
                    System.exit(0);
        }

        return;
	}

	private void expenseDelete() {
		System.out.println("Enter Expense Id to Delete: ");
		int id = Console.readInt();
		
		expenseMemory.delete(id);
		
	}

	private void incomeDelete() {
		System.out.println("Enter Income Id to Delete: ");
		int id = Console.readInt();
		
		incomeMemory.delete(id);		
		
	}

	private void displayReport() {
		System.out.println("1- Income Report");
		System.out.println("2- Expense Report");
		
        String choice = Console.readLine();

        switch (choice) {
        case "1":  incomeReport();
        			break;
        			
        case "2":   expenseReport();
                    break;

        default:    System.out.println("Invalid Choice exiting...");
                    System.exit(0);
        }

        return;
	}
	
	private void expenseReport() {
		System.out.println("1- Display Date Wise");
		System.out.println("2- Display Category Wise");
        
		String choice = Console.readLine();

        switch (choice) {
        case "1":  dateWiseExpenseReport();
        			break;
        			
        case "2":   categoryWiseExpenseReport();
                    break;

        default:    System.out.println("Invalid Choice exiting...");
                    System.exit(0);
        }

        return;
		
	}
	
	private void categoryWiseExpenseReport() {
        System.out.println("Enter Category Name: ");
        String categoryName = Console.readLine();
        
        List<Expense> expenses = expenseMemory.findAll();
        for (int i=0; i < expenses.size(); i++) {
			if(expenses.get(i).getCategory().getCategoryName().equals(categoryName) )
				expenses.remove(i);
		}
        
        for (Expense expense : expenses) {
        	System.out.println("Category Wise Expense Report: ");
        	
        	System.out.println("Expense Id: ");
			System.out.println(expense.getId());
			
			System.out.println("Category Name: ");
			System.out.println(expense.getCategory().getCategoryName());
			
			System.out.println("Labels: ");
			List<Label> labels = expense.getLabels();
			for (Label label : labels) {
				System.out.println("-" + label.getLabelName());
			}
						
			System.out.println("Total Amount: ");
			System.out.println(expense.getTotal());
			
			System.out.println("Date: ");
			System.out.println(	expense.getDate().get(Calendar.DAY_OF_MONTH) + "-" +
								expense.getDate().get(Calendar.MONTH) + "-" +
								expense.getDate().get(Calendar.YEAR));
		}
		
	}

	private void dateWiseExpenseReport() {
        System.out.println("To Enter Date Range: ");
        
		System.out.println("Enter From Date: ");
		Calendar fromDate  = Console.readDate();
		
		System.out.println("Enter To Date: ");
		Calendar toDate = Console.readDate();

        
        List<Expense> expenses = expenseMemory.findAll();
        for (int i=0; i < expenses.size(); i++) {
			if( expenses.get(i).getDate().compareTo(fromDate) <= 0  && 
					expenses.get(i).getDate().compareTo(toDate)   >= 0 )
				expenses.remove(i);
		}
        
        for (Expense expense : expenses) {
        	System.out.println("Date Wise Income Report: ");
        	
        	System.out.println("Income Id: ");
			System.out.println(expense.getId());
			
			System.out.println("Category Name: ");
			System.out.println(expense.getCategory().getCategoryName());
			
			System.out.println("Items: ");
			List<Item> items = expense.getItems();
			for (Item item : items) {
				System.out.println("-" + item.getName());
				System.out.println("-" + item.getQty());
				System.out.println("-" + item.getUnit().getUnitName());
				System.out.println("-" + item.getUnitPrice());
				System.out.println("-" + item.getDiscount());
				System.out.println("-" + item.getAmount());

			}
						
			System.out.println("Total Amount: ");
			System.out.println(expense.getTotal());
			
			System.out.println("Date: ");
			System.out.println(	expense.getDate().get(Calendar.DAY_OF_MONTH) + "-" +
					expense.getDate().get(Calendar.MONTH) + "-" +
					expense.getDate().get(Calendar.YEAR));
		}
		
	}
	
	private void categoryWiseIncomeReport() {
        System.out.println("Enter Category Name: ");
        String categoryName = Console.readLine();
        
        List<Income> incomes = incomeMemory.findAll();
        for (int i=0; i < incomes.size(); i++) {
			if(incomes.get(i).getCategory().getCategoryName().equals(categoryName) )
				incomes.remove(i);
		}
        
        for (Income income : incomes) {
        	System.out.println("Category Wise Income Report: ");
        	
        	System.out.println("Income Id: ");
			System.out.println(income.getId());
			
			System.out.println("Category Name: ");
			System.out.println(income.getCategory().getCategoryName());
			
			System.out.println("Amount: ");
			System.out.println(income.getAmount());
			
			System.out.println("Date: ");
			System.out.println(	income.getDate().get(Calendar.DAY_OF_MONTH) + "-" +
								income.getDate().get(Calendar.MONTH) + "-" +
								income.getDate().get(Calendar.YEAR));
		}
		
	}

	private void dateWiseIncomeReport() {
        System.out.println("To Enter Date Range: ");
        
		System.out.println("Enter From Date: ");
		Calendar fromDate  = Console.readDate();
		
		System.out.println("Enter To Date: ");
		Calendar toDate = Console.readDate();

        
        List<Income> incomes = incomeMemory.findAll();
        for (int i=0; i < incomes.size(); i++) {
			if( incomes.get(i).getDate().compareTo(fromDate) <= 0  && 
				incomes.get(i).getDate().compareTo(toDate)   >= 0 )
					incomes.remove(i);
		}
        
        for (Income income : incomes) {
        	System.out.println("Date Wise Income Report: ");
        	
        	System.out.println("Income Id: ");
			System.out.println(income.getId());
			
			System.out.println("Category Name: ");
			System.out.println(income.getCategory().getCategoryName());
			
			System.out.println("Amount: ");
			System.out.println(income.getAmount());
			
			System.out.println("Date: ");
			System.out.println(	income.getDate().get(Calendar.DAY_OF_MONTH) + "-" +
								income.getDate().get(Calendar.MONTH) + "-" +
								income.getDate().get(Calendar.YEAR));
		}
		
	}

	private void incomeReport() {
		System.out.println("1- Display Date Wise");
		System.out.println("2- Display Category Wise");
        
		String choice = Console.readLine();

        switch (choice) {
        case "1":  dateWiseIncomeReport();
        			break;
        			
        case "2":   categoryWiseIncomeReport();
                    break;

        default:    System.out.println("Invalid Choice exiting...");
                    System.exit(0);
        }

        return;
		
	}
	
	private void newTransaction() {
		System.out.println("1- Income");
		System.out.println("2- Expense");
		
		String choice = Console.readLine();
		
		switch (choice) {
		case "1": newIncome();
				  break;
			
		case "2": newExpense();
				  break;

		default:
			break;
		}
	}
	
	private void newExpense() {
		System.out.println("Enter Expense Id");
		int id = Console.readInt();
		
		System.out.println("To Enter Category: ");
		int catId = newCategory();
		
		System.out.println("Enter Date: ");
		Calendar date = Console.readDate();
		
		System.out.println("Enter Item; ");
		List<Item> items = newItems();
		
		System.out.println("To Enter Label; ");
		List<Label> lables = newLabels();
		
		expenseMemory.insert(new Expense(id, items, lables, categoryMemory.findById(catId), date));
	}

	private List<Item> newItems() {
		
		do {
			System.out.println("Enter Item Id: ");
			int id = Console.readInt();
			
			System.out.println("Enter Item Name: ");
			String name = Console.readLine();
			
			System.out.println("To Enter Unit: ");
			int unitId = newUnit();
			
			System.out.println("Enter Qty: ");
			int qty = Console.readInt();
			
			System.out.println("Enter Unit Price: ");
			int unitPrice = Console.readInt();
			
			
			itemMemory.insert(new Item(id, name, unitMemory.findById(unitId), qty, unitPrice));
			
			System.out.println("Enter another item? y/n ");
		} while(Console.readLine().toLowerCase().equals("y"));
		

		return itemMemory.findAll(); 
	}
	
	private List<Label> newLabels() {
		
		do {
			System.out.println("Enter Label Id: ");
			int id = Console.readInt();
			
			System.out.println("Enter Label Name: ");
			String name = Console.readLine();
			
			labelMemory.insert(new Label(id, name));
			
			System.out.println("Enter another item? y/n ");
		} while(Console.readLine().toLowerCase().equals("y"));
		

		return labelMemory.findAll(); 
	}

	private int newUnit() {
		System.out.println("Enter Unit Id: ");
		int id = Console.readInt();
		
		System.out.println("Enter Unit Name: ");
		String unt = Console.readLine();
		
		unitMemory.insert(new Unit(id, unt));
		
		return id;
	}
		
	private void newIncome() {
		System.out.println("Enter Income Id");
		int id = Console.readInt();
		
		System.out.println("To Enter Category: ");
		int catId = newCategory();
		
		System.out.println("Enter Date: ");
		Calendar date = Console.readDate();
		
		System.out.println("Enter Amount; ");
		int amount = Console.readInt();
		
		incomeMemory.insert(new Income(id, categoryMemory.findById(catId), amount, date));
	}
	
	private int newCategory() {
		System.out.println("Enter Category Id");
		int id = Console.readInt();
		
		System.out.println("Enter Category Name");
		String cat = Console.readLine();
		
		categoryMemory.insert(new Category(id, cat));
		
		return id;
	}
	
}
